var CatanServer = function (name, client, url) {
  var log = function(s) {
    window.log('[ server ' + name + ' ] ' + s);
  };
  
  log('creating CatanServer with url ' + url);
  var ws = new WebSocket(url);
  var server = this;
  
  this.send = function(type, data) {
    data = data || {}
    data.token   = this.token;
    data.game_id = (data.game_id == null ? this.game_id : data.game_id);
    var msg = {
      type: type,
      data: data
    };
    if (!this.connected) {
      log('error sending message [' + msg.type + '], not connected to server!');
      return;
    }
    console.log('[ server ' + this.name +  ' ] -> ['
                    + msg.type + '] message sent with data ' + JSON.stringify(data, null));
    
    ws.send(JSON.stringify(msg));
  };
  this.name       = name;
  this.client     = client;
  this.connected  = false;
  this.socket     = ws;
  
  this.init = function() {
    var gen_stub_fn = function(msgtype) {
      return (function(data) {
        this.send(msgtype, data || {});
      });
    };

    for (var i=0; i<= server_api.length; i++ ) {
      var type = server_api[i];
      this[type] = gen_stub_fn(type);
    }
    this.register();
  }
  
  ws.onerror = function(e) {
    log('websocket error occurred - ' + e);
  }
  
  ws.onopen = function() {
    log('connected!');
    server.connected = true;
    server.init();

    ws.onmessage = function(s) {
      var msg = JSON.parse(s.data);
      console.log('[ server ' + server.name + ' ] <- [' + msg.type + '] '
                    + 'received with data: ', msg.data);
      
      if (msg.type == 'registration_accepted') {
        client.token = server.token = msg.data.token;
      }
      else if (msg.type == 'update_context') {
        server.game_id = msg.data.id;
      }
      server.client[msg.type](msg.data);
    };
  };
  
  ws.onclose = function() {
    log('connection closed');
  };
  
  var server_api = [
    'register',
    'host_game',
    'send_message',
    'join_game',
    'game_list',
    'start_game',
    'init_settlement',
    'init_road',
    'end_turn',
    'buy_settlement',
    'buy_road',
    'buy_devcard',
    'buy_city',
    'devcard_action'      // devcard token, action=monopoly|knight|plenty|buildroad 
  ];
};